Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework messages serialization #352

Merged
merged 35 commits into from
Nov 26, 2024
Merged

Rework messages serialization #352

merged 35 commits into from
Nov 26, 2024

Conversation

Shatur
Copy link
Contributor

@Shatur Shatur commented Nov 13, 2024

The performance is a bit slower, but we getting a free byte per changed entity and several bytes per message.
For example, in our statistic test we using only 16 bytes for a test message instead of 33.

While writing the documentation, I decided to rename InitMessage to ChangeMessage and UpdateMessage to MutateMessage (and related types). This change helps make it clear that MutateMessage stores only component mutations. In contrast, ChangeMessage stores any type of change and may even include mutations if there is an insertion or removal. I considered including the rename into a separate PR, but decided to keep it here since the messages got completely reworked.

I would recommend to start reading from change_message and mutate_message modules, they contain a lot of internal documentation and description about how the new approach works.

I also switched to plain Vec for serialization since we no longer need Cursor for it
and Writer::write_all is much slower then Vec::extend_from_slice.

See comments in the code for details.
I also switched to plain `Vec` for serialization since we no longer need `Cursor` for it
and `Writer::write_all` is much slower then `Vec::extend_from_slice`.
@Shatur Shatur requested a review from UkoeHB November 13, 2024 01:26
@Shatur Shatur linked an issue Nov 13, 2024 that may be closed by this pull request
@Shatur Shatur changed the title Optimize replication message packing Optimize replication message sizes Nov 13, 2024
@Shatur Shatur changed the title Optimize replication message sizes Optimize replication message size Nov 13, 2024
Copy link

codecov bot commented Nov 13, 2024

Codecov Report

Attention: Patch coverage is 94.68268% with 31 lines in your changes missing coverage. Please review.

Project coverage is 89.71%. Comparing base (df44894) to head (d317805).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/client.rs 91.87% 13 Missing ⚠️
src/core/replication/replicated_clients.rs 87.50% 5 Missing ⚠️
src/core/event_registry/server_event.rs 69.23% 4 Missing ⚠️
src/server.rs 96.15% 4 Missing ⚠️
src/server/replication_messages/serialized_data.rs 91.17% 3 Missing ⚠️
src/server/replication_messages/change_message.rs 98.36% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #352      +/-   ##
==========================================
+ Coverage   89.32%   89.71%   +0.39%     
==========================================
  Files          41       44       +3     
  Lines        2388     2450      +62     
==========================================
+ Hits         2133     2198      +65     
+ Misses        255      252       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Shatur Shatur changed the title Optimize replication message size Rework messages serialization Nov 17, 2024
Copy link
Collaborator

@UkoeHB UkoeHB left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good. I think we tried a similar approach with ranges a while back but scrapped it due to perf.

Comment on lines +22 to +23
- Rename `ReplicationChannel::Init` into `ReplicationChannel::Changes`.
- Rename `ReplicationChannel::Update` into `ReplicationChannel::Mutations`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Rename `ReplicationChannel::Init` into `ReplicationChannel::Changes`.
- Rename `ReplicationChannel::Update` into `ReplicationChannel::Mutations`.
- Rename `ReplicationChannel::Init` into `ReplicationChannel::Update`.
- Rename `ReplicationChannel::Update` into `ReplicationChannel::Mutations`.

What do you think about this instead? It would disambiguate the message type from the internal subsection called 'changes'. Changes also seems slightly off to me for the message name.

If you agree, let's change it in a follow-up PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree!

src/client.rs Outdated Show resolved Hide resolved
src/client.rs Outdated Show resolved Hide resolved
src/client.rs Outdated Show resolved Hide resolved
src/client.rs Outdated Show resolved Hide resolved
src/server/replication_messages/mutate_message.rs Outdated Show resolved Hide resolved
src/server.rs Outdated Show resolved Hide resolved
Comment on lines 423 to 427
for ((message, _), client) in messages.iter_mut().zip(replicated_clients.iter_mut()) {
client.remove_despawned(entity);
message.write_entity(&mut shared_bytes, entity)?;
message.add_despawn(entity_range.clone());
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm do we need to filter out clients that don't have visibility of the despawned entity? Despawn messages could be considered an information leak.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed this as well while worked on this PR! Maybe in a follow-up since it were like this before?

src/server.rs Show resolved Hide resolved
Comment on lines +370 to +371
if !mutate_message.is_empty() {
let server_tick = write_tick_cached(&mut server_tick_range, serialized, server_tick)?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if !mutate_message.is_empty() {
let server_tick = write_tick_cached(&mut server_tick_range, serialized, server_tick)?;
if !mutate_message.is_empty() {
debug_assert!(change_message.is_empty());
let server_tick = write_tick_cached(&mut server_tick_range, serialized, server_tick)?;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this one was missed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this one related to the change message not consuming the whole mutate message? I.e. it's possible for mutate message to be sent with change message.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok seems that way. For some reason I thought if we had a 'Changes' message then there wouldn't be a 'Mutation' message.

Copy link
Contributor Author

@Shatur Shatur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Applied or answered all suggestions except https://github.com/projectharmonia/bevy_replicon/pull/352/files#r1855691304, will back to it tomorrow.

Comment on lines +22 to +23
- Rename `ReplicationChannel::Init` into `ReplicationChannel::Changes`.
- Rename `ReplicationChannel::Update` into `ReplicationChannel::Mutations`.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree!

src/client.rs Outdated Show resolved Hide resolved
src/client.rs Outdated
let flags = ChangeMessageFlags::from_bits_retain(cursor.read_fixedint()?);
debug_assert!(!flags.is_empty(), "message can't be empty");

let message_tick = DefaultOptions::new().deserialize_from(&mut cursor)?;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, will revert this part and add a comment.

Perhaps you could use one of the ChangeMessageFlags

Sounds good, but I will leave it for a follow-up.

src/client.rs Outdated Show resolved Hide resolved
src/client.rs Outdated
Comment on lines 298 to 302
let len = apply_dyn_array(&mut Cursor::new(&*mutate.message), |cursor| {
apply_mutations(world, params, cursor, mutate.message_tick)
});

match len {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep it as is. I usually don't write *_result or *_option. In Rust it's common to shadow the name if it's the same thing, but with a different type.

Comment on lines +379 to +384
if let Some(mut history) = client_entity.get_mut::<ConfirmHistory>() {
history.set_last_tick(message_tick);
} else {
commands
.entity(client_entity.id())
.insert(ConfirmHistory::new(message_tick));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already did it, but in the history rework PR 🙂 Let's keep it as is for this PR to avoid resolving conflicts.

Comment on lines 423 to 427
for ((message, _), client) in messages.iter_mut().zip(replicated_clients.iter_mut()) {
client.remove_despawned(entity);
message.write_entity(&mut shared_bytes, entity)?;
message.add_despawn(entity_range.clone());
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed this as well while worked on this PR! Maybe in a follow-up since it were like this before?

src/server.rs Show resolved Hide resolved
src/server/replication_messages/mutate_message.rs Outdated Show resolved Hide resolved
src/server/replication_messages/mutate_message.rs Outdated Show resolved Hide resolved
Copy link
Contributor Author

@Shatur Shatur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@UkoeHB done!

src/client.rs Outdated Show resolved Hide resolved
src/server.rs Show resolved Hide resolved
src/server/replication_messages/mutate_message.rs Outdated Show resolved Hide resolved
@Shatur Shatur merged commit 0c7f059 into master Nov 26, 2024
7 checks passed
@Shatur Shatur deleted the ser-de-rework branch November 26, 2024 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Init message header
2 participants